package pATT.profilingAlgorithm.PersonalSearcher;
/***************************************************************************
 *                               TagTokenizer                              * 
 *                       initial version by: Travis Bauer                  *
 *                      copyright (C) 2000 IGLU Research Group             *
 *                             trbauer@indiana.edu                         *
 ***************************************************************************/
/***************************************************************************
 * The licence for this code is included in LICENSE.txt.  If you did not   *
 * get this file with this distribution, request a copy from               *
 * iglu@cs.indiana.edu                                                     *
 ***************************************************************************/

import java.util.LinkedList;
import java.util.Enumeration;
import java.util.NoSuchElementException;

/** Like StringTokenizer, but uses strings, rather than characters, as tokens.
 * 
 * @author Travis Bauer <a 
 *     href="mailto:trbauer@indiana.edu">trbauer@indiana.edu</a>
 * @version 0.1
 */
public class TagTokenizer implements Enumeration {
    
  /** Contains a list of the ranges in the string to return as tokens
   */
  private LinkedList ranges = new LinkedList();
  /** The next range to return
   */
  private int index = 0;
  /** Internal copy of the string
   */
  private String original = null;

  /** Creates new TagTokenizer
   * 
   * @param str What to break up
   * @param delim The items to tokenize on.
   */
  public TagTokenizer(String str, String[] delim) {
    original = str;
    breakEmUp(str, delim, false, true);
  }
    
  /** Creates a new TagTokenizer, optionally return the tags as tokens
   * 
   * @param str What to break up.
   * @param delim The tags to tokenize on
   * @param returnTags Return the tage as strings.
   */
  public TagTokenizer(String str, String[] delim, boolean returnTags) {
    original = str;
    breakEmUp(str, delim, returnTags, true);
  }
    
  /** creates a new TagTokenizer, optionally return the tags and letting you
   * specify case sensitivity
   * 
   * @param str What to break up
   * @param delim The tags to tokenize on
   * @param returnTags Return the tags as tokens
   * @param caseSensitive Should the tokenization be case sensitive.
   */
  public TagTokenizer(String str, String[] delim, boolean returnTags, boolean caseSensitive) {
    original = str;
    breakEmUp(str, delim, returnTags, caseSensitive);
  }
    
  /** Break up the string into its parts
   * 
   * @param str 
   * @param delim 
   * @param returnTags 
   * @param caseSensitive 
   */
  @SuppressWarnings("unchecked")
private void breakEmUp(String str, String[] delim, boolean returnTags, boolean caseSensitive) {
    if (str==null) return;
    int strIndex = 0;
        
    //account for case sensitivity
    String localStr = caseSensitive?str:str.toUpperCase();
    String localDelim[] = new String[delim.length];
    for (int i = 0; i<delim.length; i++) 
      localDelim[i]=caseSensitive?delim[i]:delim[i].toUpperCase();
        
    //loop while we keep finding delimiters
    while (strIndex<str.length()) {
      int closest = str.length();
      int whichTag = -1;
      //figure out which is the first tag to appear
      for (int i = 0; i<delim.length; i++) {
	int loc = localStr.indexOf(localDelim[i], strIndex);
	if ((loc>-1) && (loc<closest)) {
	  closest = loc;
	  whichTag = i;
	}
      }
      if (strIndex!=closest)
	ranges.add(new Range(strIndex, closest));
      strIndex=closest;
      if (whichTag!=-1) {
	if (returnTags)
	  ranges.add(new Range(closest, closest+delim[whichTag].length()));
	strIndex+=delim[whichTag].length();
      }
    }
                
  }

  /** How many tokens there are in the string.
   */
  public int countTokens() {
    return ranges.size();
  }
    
  /** Whether there are more Elements to return.
   */
  public boolean hasMoreElements() {
    return hasMoreTokens();
  }
    
  /** Whether there are more tokens to return.
   */
  public boolean hasMoreTokens() {
    return (index<ranges.size());
  }
    
  /** Get the next token.
   */
  public String nextToken() {
    if (index>=ranges.size())
      throw new NoSuchElementException("No more tokens");
    Range r = (Range)ranges.get(index);
    index++;
    return original.substring(r.start, r.end);
  }
    
  /** Get the next Element
   */
  public Object nextElement() {
    return nextToken();
  }
    
  private static class Range {
    /**          * 
     * @param start 
     * @param end 
     */
    public Range(int start, int end) {
      this.start=start;
      this.end=end;
    }
    /**          */
    public int start;
    /**          */
    public int end;
  }
    
  /** A simple test.
   * 
   * @param argv 
   */
  public static void main (String argv[]) {
    String testStr =
      "<b>this is bold text</b>this is not<b>more bold text</b>";
    TagTokenizer tt = new TagTokenizer(testStr, new String[] {"<b>", "</b>"});
    while (tt.hasMoreTokens()) {
      System.out.println(tt.nextToken());
    }
//    System.exit(0);
  }
}
